package com.syh.jn.scm.infrastructure.repository.impl.supplier.purchase;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.core.ddd.infrastructure.repository.AggregateRepoHibernateImplTmpl;
import com.syh.core.expction.DataModelException;
import com.syh.jn.scm.domain.supplier.entity.purchase.PurchaseOrder;
import com.syh.jn.scm.domain.supplier.entity.purchase.PurchaseOrderItem;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseOrderRepository;
import com.syh.jn.scm.dto.supplier.purchase.PurStatisticalAmountVo;
import com.syh.jn.scm.dto.supplier.purchase.PurchaseOrderItemVo;
import com.syh.jn.scm.dto.supplier.purchase.PurchaseOrderVo;
import com.syh.jn.scm.dto.supplier.sale.SaleStatisticalAmountVo;
import com.syh.jn.scm.exception.BusinessException;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsBrandModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsCategoryModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsModel;
import com.syh.jn.scm.infrastructure.repository.model.purchase.PurchaseOrderItemModel;
import com.syh.jn.scm.infrastructure.repository.model.purchase.PurchaseOrderModel;
import com.syh.jn.scm.infrastructure.repository.utils.MybatisTemplate;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 采购订单管理(供应商)
 */
@Repository
public class PurchaseOrderRepositoryImpl implements PurchaseOrderRepository {

  private HibernateTemplate hibernateTemplate;
  private AggregateRepoHibernateImplTmpl<PurchaseOrder,PurchaseOrderModel,Long> purchaseOrderRepoHibernateImpl;
  private AggregateRepoHibernateImplTmpl<PurchaseOrderItem, PurchaseOrderItemModel, Long> purchaseOrderItemRepoHibernateImpl;

  @Autowired
  public PurchaseOrderRepositoryImpl(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
    purchaseOrderRepoHibernateImpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(this.hibernateTemplate).entityClass(PurchaseOrder.class).modelClass(PurchaseOrderModel.class).idClass(Long.class).build();
    purchaseOrderItemRepoHibernateImpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(this.hibernateTemplate).entityClass(PurchaseOrderItem.class).modelClass(PurchaseOrderItemModel.class).idClass(Long.class).build();
  }
  /**
   * 新增采购订单
   *
   * @param purchaseOrder
   * @return
   */
  @Override
  public Long add(PurchaseOrder purchaseOrder) {
    PurchaseOrderModel purchaseOrderModel = this.purchaseOrderRepoHibernateImpl.add(purchaseOrder);
    this.saveOrderItems(purchaseOrderModel.getId(), purchaseOrder.getItems());
    return purchaseOrderModel.getId();
  }

  /**
   * 修改采购订单
   *
   * @param purchaseOrder
   */
  @Override
  public void update(PurchaseOrder purchaseOrder) {
    this.purchaseOrderRepoHibernateImpl.update(purchaseOrder);
    //删除订单项
    this.removeItem(purchaseOrder.getId());
    //保存新的采购订单项
    this.saveOrderItems(purchaseOrder.getId(), purchaseOrder.getItems());
  }

  @Override
  public PurchaseOrder getById(Long id) {
    PurchaseOrder purchaseOrder = this.purchaseOrderRepoHibernateImpl.getById(id);
    if (purchaseOrder == null) {
      return purchaseOrder;
    }
    purchaseOrder.setItems(this.getItemsByPurchaseOrderId(id));
    return purchaseOrder;
  }

  @Override
  public PurchaseOrder getOne(Wrapper wrapper) {
    PurchaseOrder purchaseOrder = this.purchaseOrderRepoHibernateImpl.getOne(wrapper);
    if (purchaseOrder == null) {
      return purchaseOrder;
    }
    purchaseOrder.setItems(this.getItemsByPurchaseOrderId(purchaseOrder.getId()));
    return purchaseOrder;
  }

  /**
   * 删除
   *
   * @param purchaseOrder
   */
  @Override
  public void remove(PurchaseOrder purchaseOrder) {
    this.removeById(purchaseOrder.getId());
  }


  @Override
  public void removeById(Long id) {
    this.removeItem(id);
    this.purchaseOrderRepoHibernateImpl.removeById(id);
  }

  /**
   * 删除订单项
   *
   * @param purchaseOrderId
   */
  private void removeItem(Long purchaseOrderId) {
    String hql = "from PurchaseOrderItemModel model where model.purchaseOrderId = ?";
    List<PurchaseOrderItemModel> itemModelList = (List<PurchaseOrderItemModel>) this.hibernateTemplate.find(hql, purchaseOrderId);
    itemModelList.stream().forEach(item -> {
      this.hibernateTemplate.delete(item);
    });
  }

  /**
   * 保存当前采购订单对应的订单项
   *
   * @param id
   * @param items
   */
  private void saveOrderItems(Long id, List<PurchaseOrderItem> items) {
    items.stream().forEach(item -> {
      PurchaseOrderItemModel itemModel = new PurchaseOrderItemModel();
      GoodsModel goodsModel = this.hibernateTemplate.get(GoodsModel.class, item.getGoodsId());
      GoodsBrandModel goodsBrandModel = new GoodsBrandModel();
      if (goodsModel.getGoodsBrandId() != null) {
        goodsBrandModel = this.hibernateTemplate.get(GoodsBrandModel.class, goodsModel.getGoodsBrandId());
      }
      GoodsCategoryModel goodsCategoryModel = new GoodsCategoryModel();
      if (goodsModel.getCategoryId() != null) {
        goodsCategoryModel = this.hibernateTemplate.get(GoodsCategoryModel.class, goodsModel.getCategoryId());
      }
      PurchaseOrderModel purchaseOrderModel = this.hibernateTemplate.get(PurchaseOrderModel.class, id);

      ExtBeanUtils.copyProperties(item, itemModel);
      itemModel.setPurchaseOrderId(id);
      itemModel.setBusinessEntityId(purchaseOrderModel.getBusinessEntityId());
      //在仓储层冗余是为了安全和数据的准确
      itemModel.setGoodsName(goodsModel.getName());
      itemModel.setSpecName(goodsModel.getSpecName());
      itemModel.setGoodsCode(goodsModel.getCode());
      itemModel.setIsDefaultGoods(goodsModel.getIsDefaultGoods());
      itemModel.setConversionRate(goodsModel.getConversionRate());
      itemModel.setCodeBar(goodsModel.getCodeBar());
      itemModel.setUnits(goodsModel.getUnits());
      itemModel.setCategoryId(goodsModel.getCategoryId());
      itemModel.setCategoryName(goodsCategoryModel.getName());
      itemModel.setCategoryCatalogCode(goodsCategoryModel.getCatalogCode());
      itemModel.setGoodsBrandId(ExtStringUtils.isBlank(goodsModel.getGoodsBrandId()) ? null : goodsModel.getGoodsBrandId());
      itemModel.setGoodsBrandName(ExtStringUtils.isBlank(goodsBrandModel.getName()) ? null : goodsBrandModel.getName());
      this.hibernateTemplate.save(itemModel);
    });
  }

  /**
   * 根据归属id获取明细
   *
   * @param purchaseOrderId
   * @return
   */
  @Override
  public List<PurchaseOrderItem> getItemsByPurchaseOrderId(Long purchaseOrderId) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq("purchaseOrderId",purchaseOrderId));
    List<PurchaseOrderItem> purchaseOrderItems = this.purchaseOrderItemRepoHibernateImpl.getList(wrapper);
    return purchaseOrderItems;
  }

  /**
   * 根据归属id获取明细
   *
   * @param purchaseOrderIds
   * @return
   */
  @Override
  public List<PurchaseOrderItem> getItemsByPurchaseOrderIds(Long[] purchaseOrderIds) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.in("purchaseOrderId",purchaseOrderIds));
    List<PurchaseOrderItem> purchaseOrderItems = this.purchaseOrderItemRepoHibernateImpl.getList(wrapper);
    return purchaseOrderItems;
  }


  /**
   * 重载更新方法  选择是否更新订单项
   *
   * @param order
   * @param isUpdateItem true：更新订单项 false：不更新订单项
   */
  public void update(PurchaseOrder order, boolean isUpdateItem) {
    if (isUpdateItem) {
      this.update(order);
    } else {
      this.purchaseOrderRepoHibernateImpl.update(order);
    }
  }

  /**
   * 根据商品id拿到订单明细商品
   *
   * @param goodsId
   * @return
   */
  @Override
  public PurchaseOrderItem getByGoodsId(Long goodsId, Long id) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq("goodsId",goodsId)).append(Restrictions.eq("id",id));
    PurchaseOrderItem purchaseOrderItem = this.purchaseOrderItemRepoHibernateImpl.getOne(wrapper);
    return purchaseOrderItem;
  }

  @Override
  public PurchaseOrderItem getItemByItemId(Long itemId) {
    return this.purchaseOrderItemRepoHibernateImpl.getById(itemId);
  }

  /**
   * 上传单据图片
   *
   * @param order
   */
  @Override
  public void upload(PurchaseOrder order) {
    this.purchaseOrderRepoHibernateImpl.update(order);
  }

  /**
   * 根据服务商id删除采购单
   * @param businessEntityId
   */
  @Override
  public void deleteByBusinessEntityId(Long businessEntityId) {
    String itemHql = "delete from PurchaseOrderItemModel where businessEntityId = :businessEntityId";
    Query itemQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(itemHql);
    itemQuery.setParameter("businessEntityId",businessEntityId);
    itemQuery.executeUpdate();
    String orderHql = "delete from PurchaseOrderModel where businessEntityId = :businessEntityId";
    Query orderQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(orderHql);
    orderQuery.setParameter("businessEntityId",businessEntityId);
    orderQuery.executeUpdate();
  }

  @Override
  public boolean contains(Long id) {
    return this.purchaseOrderRepoHibernateImpl.contains(id);
  }

  @Override
  public  List<PurchaseOrder> getList(Wrapper wrapper) {
    return this.purchaseOrderRepoHibernateImpl.getList(wrapper);
  }

  @Override
  public List<PurchaseOrder> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return this.purchaseOrderRepoHibernateImpl.findListPage(wrapper,startRow,count);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return this.purchaseOrderRepoHibernateImpl.getCount(wrapper);
  }

  /**
   * 判断采购项是否存在该商品
   *
   * @param column
   * @param id
   * @return
   */
  @Override
  public boolean purItemExistsById(String column, Long id) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq(column,id));
    return this.purchaseOrderItemRepoHibernateImpl.getCount(wrapper) > 0;
  }

  /**
   * 统计采购金额
   *
   * @param wrapper
   * @return
   */
  @Override
  public PurStatisticalAmountVo statisticalAmount(Wrapper wrapper) {
    return null;
  }

  @Override
  public PurStatisticalAmountVo statisticalAmountByOrder(Wrapper we) {
    return null;
  }

  @Override
  public void updateOrderAndItems(PurchaseOrder order) {
    PurchaseOrderModel orderModel = this.hibernateTemplate.get(PurchaseOrderModel.class, order.getId());
    if (orderModel == null) {
      throw new DataModelException("订单不存在");
    }
    ExtBeanUtils.copyProperties(order, orderModel);
    this.hibernateTemplate.update(orderModel);
    //更新订单项
    order.getItems().forEach(orderItem -> {
      PurchaseOrderItemModel model = this.hibernateTemplate.get(PurchaseOrderItemModel.class, orderItem.getId());
      if (model == null) {
        throw new DataModelException("对应明细不存在");
      }
      ExtBeanUtils.copyProperties(orderItem, model);
      this.hibernateTemplate.update(model);
    });
  }
}
